const Koa = require("koa");
const fs = require("fs");
const path = require("path");
const compilerSFC = require("@vue/compiler-sfc");
const compilerDOM = require("@vue/compiler-dom");

const app = new Koa();

app.use(async (ctx) => {
  const { url, query } = ctx;
  if (url === "/") {
    ctx.type = "text/html";
    ctx.body = fs.readFileSync(path.join(__dirname, "index.html"), "utf-8");
  } else if (url.endsWith(".js")) {
    const p = path.join(__dirname, url); // 首先找到文件的位置
    ctx.type = "application/javascript"; // 这里如果不设置的话，默认是 text/plain
    ctx.body = rewriteImport(fs.readFileSync(p, "utf-8"));
  } else if (url.startsWith("/@modules/")) {
    // console.log("裸模块的加载");
    const moduleName = url.replace("/@modules/", "");
    const p = path.join(__dirname, "node_modules", moduleName);
    const modulePath = require(path.join(p, "/package.json")).module; // 这里的 json 是 require 引入
    const realPath = path.join(p, modulePath);
    ctx.type = "application/javascript";
    ctx.body = rewriteImport(fs.readFileSync(realPath, "utf-8"));
  } else if (url.indexOf(".vue") > -1) {
    const p = path.join(__dirname, url.split("?")[0]); // 找到文件位置
    const content = fs.readFileSync(p, "utf-8"); // 以纯文本读取
    const compileContent = compilerSFC.parse(content); // vue 词法分析
    const { type } = query;
    if (!type) {
      // 获取组件中的脚本
      const { content: scriptContent } = compileContent.descriptor.script;
      const script = scriptContent.replace(
        "export default ",
        "const __script = "
      ); // 将组件中的脚本变成变量
      ctx.type = "application/javascript";
      ctx.body = `
        ${rewriteImport(script)}
        import { render as __render } from '${url}?type=template'   // 请求 html 获取，render 函数
        __script.render = __render    // 将 render 函数 挂载到 脚本变量 中
        export default __script   // 导出脚本变量
      `;
    } else if (type === "template") {
      const { content: templateContent } = compileContent.descriptor.template;
      const render = compilerDOM.compile(templateContent, {
        mode: "module",
      }).code;
      console.log("render:>>", render);
      ctx.type = "application/javascript";
      ctx.body = rewriteImport(render);
    }
  }
});

function rewriteImport(content) {
  return content.replace(/ from ['"](.*)['"]/g, function (s1, s2) {
    const startsWithResult =
      s2.startsWith("/") || s2.startsWith("./") || s2.startsWith("../");
    if (startsWithResult === true) {
      return s1;
    } else {
      return ` from "/@modules/${s2}"`;
    }
  });
}

app.listen(3000);
